package it.unibo.iss.domotica.serializer;

import com.google.inject.Inject;
import com.google.inject.Provider;
import it.unibo.iss.domotica.domoticDsl.DomoticDslPackage;
import it.unibo.iss.domotica.domoticDsl.Elettrodomestico;
import it.unibo.iss.domotica.domoticDsl.Properties;
import it.unibo.iss.domotica.domoticDsl.Sensor;
import it.unibo.iss.domotica.services.DomoticDslGrammarAccess;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
import org.eclipse.xtext.serializer.sequencer.ISemanticNodeProvider.INodesForEObjectProvider;
import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;

@SuppressWarnings("restriction")
public class AbstractDomoticDslSemanticSequencer extends AbstractSemanticSequencer {

	@Inject
	protected DomoticDslGrammarAccess grammarAccess;
	
	@Inject
	protected ISemanticSequencerDiagnosticProvider diagnosticProvider;
	
	@Inject
	protected ITransientValueService transientValues;
	
	@Inject
	@GenericSequencer
	protected Provider<ISemanticSequencer> genericSequencerProvider;
	
	protected ISemanticSequencer genericSequencer;
	
	
	@Override
	public void init(ISemanticSequencer sequencer, ISemanticSequenceAcceptor sequenceAcceptor, Acceptor errorAcceptor) {
		super.init(sequencer, sequenceAcceptor, errorAcceptor);
		this.genericSequencer = genericSequencerProvider.get();
		this.genericSequencer.init(sequencer, sequenceAcceptor, errorAcceptor);
	}
	
	public void createSequence(EObject context, EObject semanticObject) {
		if(semanticObject.eClass().getEPackage() == DomoticDslPackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
			case DomoticDslPackage.ELETTRODOMESTICO:
				if(context == grammarAccess.getElettrodomesticoRule()) {
					sequence_Elettrodomestico(context, (Elettrodomestico) semanticObject); 
					return; 
				}
				else break;
			case DomoticDslPackage.PACKAGE:
				if(context == grammarAccess.getPackageRule()) {
					sequence_Package(context, (it.unibo.iss.domotica.domoticDsl.Package) semanticObject); 
					return; 
				}
				else break;
			case DomoticDslPackage.PROPERTIES:
				if(context == grammarAccess.getPropertiesRule()) {
					sequence_Properties(context, (Properties) semanticObject); 
					return; 
				}
				else break;
			case DomoticDslPackage.SENSOR:
				if(context == grammarAccess.getSensorRule()) {
					sequence_Sensor(context, (Sensor) semanticObject); 
					return; 
				}
				else break;
			case DomoticDslPackage.SYSTEM:
				if(context == grammarAccess.getSystemRule()) {
					sequence_System(context, (it.unibo.iss.domotica.domoticDsl.System) semanticObject); 
					return; 
				}
				else break;
			}
		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
	}
	
	/**
	 * Constraint:
	 *     (name=ID consumption=Consumption usage=Usage)
	 *
	 * Features:
	 *    name[1, 1]
	 *    consumption[1, 1]
	 *    usage[1, 1]
	 */
	protected void sequence_Elettrodomestico(EObject context, Elettrodomestico semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__NAME));
			if(transientValues.isValueTransient(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__CONSUMPTION) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__CONSUMPTION));
			if(transientValues.isValueTransient(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__USAGE) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DomoticDslPackage.Literals.ELETTRODOMESTICO__USAGE));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getElettrodomesticoAccess().getNameIDTerminalRuleCall_1_0(), semanticObject.getName());
		feeder.accept(grammarAccess.getElettrodomesticoAccess().getConsumptionConsumptionEnumRuleCall_3_0(), semanticObject.getConsumption());
		feeder.accept(grammarAccess.getElettrodomesticoAccess().getUsageUsageEnumRuleCall_5_0(), semanticObject.getUsage());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     name=STRING
	 *
	 * Features:
	 *    name[1, 1]
	 */
	protected void sequence_Package(EObject context, it.unibo.iss.domotica.domoticDsl.Package semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, DomoticDslPackage.Literals.PACKAGE__NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DomoticDslPackage.Literals.PACKAGE__NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getPackageAccess().getNameSTRINGTerminalRuleCall_1_0(), semanticObject.getName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     name=STRING
	 *
	 * Features:
	 *    name[1, 1]
	 */
	protected void sequence_Properties(EObject context, Properties semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, DomoticDslPackage.Literals.PROPERTIES__NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DomoticDslPackage.Literals.PROPERTIES__NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getPropertiesAccess().getNameSTRINGTerminalRuleCall_1_0(), semanticObject.getName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     (elettrodomestico=[Elettrodomestico|ID] (minConsumption=DOUBLE maxConsumption=DOUBLE)?)
	 *
	 * Features:
	 *    elettrodomestico[1, 1]
	 *    minConsumption[0, 1]
	 *         EXCLUDE_IF_UNSET maxConsumption
	 *         MANDATORY_IF_SET maxConsumption
	 *    maxConsumption[0, 1]
	 *         EXCLUDE_IF_UNSET minConsumption
	 *         MANDATORY_IF_SET minConsumption
	 */
	protected void sequence_Sensor(EObject context, Sensor semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=ID package=Package? properties=Properties? elettrodomestico+=Elettrodomestico* sensors+=Sensor*)
	 *
	 * Features:
	 *    name[1, 1]
	 *    package[0, 1]
	 *    properties[0, 1]
	 *    elettrodomestico[0, *]
	 *    sensors[0, *]
	 */
	protected void sequence_System(EObject context, it.unibo.iss.domotica.domoticDsl.System semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
}
